//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XImage.cpp>
///	@path	~/src/gui/xgui/
///	@date	2008/10/30
///	@brief	.

#define _FULLAPI
#include "config/config.h"

#include "gui/IGuiForm.h"
#include "gui/xgui/XImage.h"
#include "gui/composite/composition.h"
#include "gui/image/ImageResource.h"

namespace xeres {

	IMPL_IOBJECT_CLASS_DYNAMIC( XImage );

	// XImage
	XImage::XImage( void )
		: IGuiControl( Rect<int>() , false , false , true )
		, m_transparency( 1 )
		, m_time( 0 )
		, m_frame( 0 )
	{
	}
	// XImage
	XImage::XImage( RefWeak<IBitmap> resource , const Rect<int>& placement )
		: IGuiControl( placement , false , false , true )
		, m_image( resource )
		, m_transparency( 1 )
		, m_time( 0 )
		, m_frame( 0 )
	{
	}
	// ~XImage
	XImage::~XImage( void )
	{
	}
	// SetParent
	bool XImage::SetParent( RefWeak<IGuiForm> parent )
	{
		if( __super::SetParent( parent ) )
		{
			if( m_image.IsValid()&& m_parent.IsValid() )
			{
				if( m_image->GetFrame() > 0 /*&& m_image->GetDelay( 0 ) > 0*/ )
				{
					m_parent->AddTickable( this );
				}
			}
			return true;
		}
		return false;
	}
	// SetImage
	void XImage::SetImage( RefWeak<IBitmap> resource )
	{
		m_image = resource;
		Rewind();
		if( m_parent.IsValid() )
		{
			if( m_image->GetFrame() > 0 /*&& m_image->GetDelay( 0 ) > 0*/ )
			{
				m_parent->AddTickable( this );
			}
			else
			{
				m_parent->DelTickable( this );
			}
		}
		UpdateControl();
	}
	// GetStyle
	RefWeak<CImageStyle> XImage::GetStyle( void )
	{
		return m_style;
	}
	// SetTransparency
	void XImage::SetTransparency( float trans )
	{
		m_transparency = clamp( trans , 0.f , 1.f );
	}
	// Rewind
	void XImage::Rewind( void )
	{
		m_time = 0;
		m_frame = 0;
		UpdateControl();
	}
	// Tick
	void XImage::Tick( Updater& updater , float dTime )
	{
		float delay = m_image->GetDelay( m_frame );
		if( delay == -1 )
		{
			++m_frame;
			if( m_frame >= m_image->GetFrame() )
				m_frame = 0;
			UpdateControl();
			return;
		}

		m_time += dTime;
		if( m_time < delay )
		{
			return;
		}

		do
		{
			m_time -= delay;
			++m_frame;
			if( m_frame >= m_image->GetFrame() )
			{
				m_frame = 0;
			}
			delay = m_image->GetDelay( m_frame );
		}while( m_time > delay );

		if( m_time < 0 )
			m_time = 0;

		UpdateControl();
	}
	// Draw
	void XImage::Draw( Composition& composition )
	{
		if( m_image.IsNull() )
			return;

		PlacementStyle& style = *m_style;
		Pair<int> pos = style.GetImageCoord( m_image->GetSize() , GetRect() );
		composition.painter().DrawBitmap( m_image , pos , GetBound() , (int)(m_transparency * 255) , m_frame );
	}
	
	IMPL_IOBJECT_CLASS_DYNAMIC( XAnimation );

	// XAnimation
	XAnimation::XAnimation( void )
		: IGuiControl( Rect<int>() , false , false , true )
		, m_play( 0 )
		, m_transparency( 1 )
		, m_speed( 24 )
		, m_rest( -1 )
	{
	}
	// XAnimation
	XAnimation::XAnimation( RefWeak<IBitmap> resource , const Rect<int>& placement )
		: IGuiControl( placement , false , false , true )
		, m_ani( resource )
		, m_play( 0 )
		, m_transparency( 1 )
		, m_speed( 24 )
		, m_rest( -1 )
	{
	}
	// ~XAnimation
	XAnimation::~XAnimation( void )
	{
	}
	// SetParent
	bool XAnimation::SetParent( RefWeak<IGuiForm> parent )
	{
		if( __super::SetParent( parent ) )
		{
			if( !IsStopped() && m_parent.IsValid() )
			{
				m_parent->AddTickable( this );
			}
			return true;
		}
		return false;
	}
	// SetImage
	void XAnimation::SetImage( RefWeak<IBitmap> resource )
	{
		m_ani = resource;
		m_play = 0;
		UpdateControl();
	}
	// GetStyle
	RefWeak<CImageStyle> XAnimation::GetStyle( void )
	{
		return m_style;
	}
	// SetTransparency
	void XAnimation::SetTransparency( float trans )
	{
		m_transparency = trans;
	}
	// SetSpeed
	void XAnimation::SetSpeed( float speed )
	{
		m_speed = speed;
	}
	// Draw
	void XAnimation::Draw( Composition& composition )
	{
		if( m_ani.IsNull() )
			return;

		PlacementStyle& style = *m_style;
		Pair<int> pos = style.GetImageCoord( m_ani->GetSize() , GetRect() );
		composition.painter().DrawBitmap( m_ani , pos , GetBound() , (int)(m_transparency * 255) , (int)m_play );
	}
	// Tick
	void XAnimation::Tick( Updater& updater , float dTime )
	{
		if( m_ani.IsNull() )
			return;

		float total = (float)m_ani->GetFrame() - 1;
		m_play += dTime * m_speed;
		if( m_play > total )
		{
			// Loop?
			if( m_rest < 0 )
			{
				// Never stop.
				m_play = 0;
			}
			else if( m_rest == 0 )
			{
				// Stopped.
				m_parent->DelTickable( this );
				m_play = 0;
			}
			else
			{
				m_rest = max( 0 , m_rest - 1 );
				if( m_rest == 0 )
				{
					// Stopped.
					m_parent->DelTickable( this );
					m_play = 0;
				}
				else
				{
					m_play = 0;
				}
			}
		}
		//m_play = clamp( m_play , 0.f , total );
		UpdateControl();
	}
	// SetPlay
	void XAnimation::SetPlayCount( int play )
	{
		m_rest = play;
		if( !IsStopped() )
		{
			m_parent->AddTickable( this );
		}
		else
		{
			m_parent->DelTickable( this );
		}
	}
	
} // namespace xeres
